package org.niux.testHtml.ui;

import java.awt.EventQueue;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.LayoutStyle.ComponentPlacement;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.AndFilter;
import org.htmlparser.filters.HasAttributeFilter;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;

public class MainUI {
	
	private Log log = LogFactory.getLog(this.getClass());
	
	private JFrame frame;
	private JTextField urlInput;
	private JScrollPane scrollPane;
	private JTextArea textArea;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					MainUI window = new MainUI();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public MainUI() {
		initialize();
		frame.setLocationRelativeTo(null); //窗体居中
		
		frame.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e){
//				Toolkit.getDefaultToolkit().beep();
				System.exit(0);
			}
		});
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setTitle("小说转换器");
		frame.getContentPane().setBackground(SystemColor.inactiveCaptionText);
		frame.setBackground(SystemColor.inactiveCaptionText);
		frame.setBounds(100, 100, 673, 496);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		urlInput = new JTextField();
		urlInput.setColumns(10);
		urlInput.setText("http://www.yi-see.com/art_17466_9628.html");
		
		JButton button = new JButton("\u5206\u6790");
		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(urlInput.getText().equals("")){
					
				} else {
					
					textArea.setText("");
					
					Thread importThread = new Thread(new Runnable() {
						public void run() {
							//获取域名
							String domain = getHost(urlInput.getText());
							
							// 创建默认的httpClient实例.
							HttpClient httpclient = new DefaultHttpClient();
							HttpGet httpget = new HttpGet(urlInput.getText());
							
							log.debug(httpget.getURI());
							
							StringBuffer allContent = new StringBuffer();
							
							try {
								textArea.append("打开小说目录页面....\r\n");
								textArea.setCaretPosition(textArea.getText().length());
								HttpResponse response = httpclient.execute(httpget);
								HttpEntity entity = response.getEntity();
								
								byte[] bytes = EntityUtils.toByteArray(entity);
								String charSet = getCharSet(bytes);
								
								textArea.append("解析目录页面....\r\n");
								textArea.setCaretPosition(textArea.getText().length());
								String html = getResource(bytes,charSet);
								
								textArea.append("正在获取书名....\r\n");
								textArea.setCaretPosition(textArea.getText().length());
								String title = getTitle(html,charSet);
								
								textArea.append("小说名为"+title+"\r\n");
								textArea.setCaretPosition(textArea.getText().length());
								log.debug(title);
								
								textArea.append("正在获取章节....\r\n");
								textArea.setCaretPosition(textArea.getText().length());
								Map<String,String> parts = getPart(html,charSet);
								
								textArea.append(title + "共有" + parts.size() + "章\r\n");
								textArea.setCaretPosition(textArea.getText().length());
								
								for(int i = 1; i <= parts.size(); i++){
									String partUrl = parts.get(Integer.toString(i));
									
									textArea.append("载入第"+i+"章页面\r\n");
									textArea.setCaretPosition(textArea.getText().length());
									httpget = new HttpGet("http://"+domain+"/"+partUrl);
									response = httpclient.execute(httpget);
									entity = response.getEntity();
									
									bytes = EntityUtils.toByteArray(entity);
									
									textArea.append("获取第"+i+"章内容页面源代码....\r\n");
									textArea.setCaretPosition(textArea.getText().length());
									html = getResource(bytes,charSet);
									
									textArea.append("获取第"+i+"章内容....\r\n");
									textArea.setCaretPosition(textArea.getText().length());
									String content = getContent(html,charSet);
									
									allContent.append("第" + i + "节\r\n");
									textArea.setCaretPosition(textArea.getText().length());
									allContent.append(content);
								}
								
								textArea.append("正在导出文本文件....\r\n");
								textArea.setCaretPosition(textArea.getText().length());
								toTxt(title,allContent.toString());
								
								textArea.append("转换成功！");
								textArea.setCaretPosition(textArea.getText().length());
							} catch (ClientProtocolException e1) {
								e1.printStackTrace();
							} catch (IOException e1) {
								e1.printStackTrace();
							}
						}
					});

					importThread.start();
				}
			}
		});
		button.setBackground(SystemColor.inactiveCaptionText);
		
		scrollPane = new JScrollPane();
		
		GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
		groupLayout.setHorizontalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
						.addGroup(groupLayout.createSequentialGroup()
							.addGap(10)
							.addComponent(urlInput, GroupLayout.DEFAULT_SIZE, 582, Short.MAX_VALUE)
							.addGap(6)
							.addComponent(button))
						.addGroup(groupLayout.createSequentialGroup()
							.addContainerGap()
							.addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 645, Short.MAX_VALUE)))
					.addContainerGap())
		);
		groupLayout.setVerticalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addGap(10)
					.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
						.addGroup(groupLayout.createSequentialGroup()
							.addGap(1)
							.addComponent(urlInput, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
						.addComponent(button))
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 413, Short.MAX_VALUE)
					.addContainerGap())
		);
		
		textArea = new JTextArea();
		textArea.setLineWrap(true); //自动换行
		
		scrollPane.setViewportView(textArea);
		scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); //不出现横向滚动条
		scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);//需要时出现纵向滚动条
		
		frame.getContentPane().setLayout(groupLayout);
	}
	
	/**
	 * 
	 * 方法概述：获取HTML源代码
	 * 描述：获取HTML源代码
	 * @param url
	 * @return
	 * 返回类型：String
	 * 修改人：梁铭显 
	 * 修改时间：2013-7-23
	 */
	public String getResource(byte[] bytes,String charSet){
		StringBuffer html = new StringBuffer();
		
		try {
			html.append(new String(bytes,charSet));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		return html.toString();
	}
	
	/**
	 * 
	 * 方法概述：获取字符编码
	 * 描述：获取字符编码
	 * @param html
	 * 返回类型：void
	 * 修改人：梁铭显 
	 * 修改时间：2013-7-24
	 */
	public String getCharSet(byte[] bytes){
		String charSet = "";
		
		String regEx = "(?=<meta).*?(?<=charset=[\\'|\\\"]?)([[a-z]|[A-Z]|[0-9]|-]*)";
		
		Pattern p = Pattern.compile(regEx);
		
		Matcher m = p.matcher(new String(bytes));
		
		if(m.find()){
			if(m.groupCount() == 1){
				charSet = m.group(1);
			}
		}
		
		log.debug(charSet);
		
		return charSet;
	}
	
	/**
	 * 
	 * 方法概述：获取小说名称
	 * 描述：获取小说名称
	 * @param html
	 * @return
	 * 返回类型：String
	 * 修改人：梁铭显 
	 * 修改时间：2013-7-24
	 */
	public String getTitle(String html,String charSet){
		String title = "";
		
		//获取书名
		Parser parser = Parser.createParser(html, charSet);//用源码和页面的字符编码初始化一个Parser处理器
		
		try {
			NodeFilter span = new TagNameFilter("SPAN");
			NodeFilter classAttr = new HasAttributeFilter("Class","T1");
			NodeFilter spanFilter = new AndFilter(span,classAttr);
			
			NodeList nodeList = parser.extractAllNodesThatMatch(spanFilter);
			
			for(int i = 0; i < nodeList.size(); i++){
				Node titleNode = (Node)nodeList.elementAt(i);
				NodeFilter a = new TagNameFilter("a");
				NodeList aNodes = titleNode.getChildren().extractAllNodesThatMatch(a);
				
				for(int n = 0; n < aNodes.size(); n++){
					LinkTag aTag = (LinkTag)aNodes.elementAt(n);
					title = aTag.getLinkText();
				}
			}
		} catch (ParserException e) {
			e.printStackTrace();
		}
		
		return title;
	}
	
	/**
	 * 
	 * 方法概述：获取章节
	 * 描述：获取章节
	 * @param html
	 * @return
	 * 返回类型：Map<String,String>
	 * 修改人：梁铭显 
	 * 修改时间：2013-7-24
	 */
	public Map<String, String> getPart(String html,String charSet){
		// 获取章节
		Parser parser = Parser.createParser(html, charSet);//用源码和页面的字符编码初始化一个Parser处理器
		
		Map<String, String> parts = new HashMap<String, String>();
		
		try {
			//章节Table
			NodeFilter table = new TagNameFilter("TABLE");
			NodeFilter width = new HasAttributeFilter("WIDTH", "900px");
			NodeFilter tablefilter = new AndFilter(table, width);

			NodeFilter cellpadding = new HasAttributeFilter("cellpadding", "0");
			NodeFilter cellpaddingFilter = new AndFilter(tablefilter, cellpadding);

			NodeFilter border = new HasAttributeFilter("border", "0");
			NodeFilter borderFilter = new AndFilter(cellpaddingFilter, border);

			NodeList nodes = parser.extractAllNodesThatMatch(borderFilter);

			for (int i = 0; i < nodes.size(); i++) {
				log.debug("=====================table=======================\r\n");
				Node textNode = (Node) nodes.elementAt(i);
				log.debug(textNode.toHtml() + "\r\n");
				log.debug("=====================table=======================\r\n");

				log.debug("\r\n");

				log.debug("=====================tr=======================\r\n");
				NodeFilter tr = new TagNameFilter("tr");
				NodeList trNodes = textNode.getChildren()
						.extractAllNodesThatMatch(tr);

				for (int j = 0; j < trNodes.size(); j++) {
					Node trNode = (Node) trNodes.elementAt(j);
					log.debug(trNode.toHtml() + "\r\n");

					NodeFilter td = new TagNameFilter("TD");
//					NodeFilter filter = new HasChildFilter(td);
					NodeList tdNodes = trNode.getChildren().extractAllNodesThatMatch(td);

					log.debug("=====================td=======================\r\n");
					for (int m = 0; m < tdNodes.size(); m++) {
						Node tdNode = (Node) tdNodes.elementAt(m);
						log.debug(tdNode.toHtml() + "\r\n");
						
						if(tdNode.getChildren() != null) {
							NodeFilter a = new TagNameFilter("a");
							NodeList aNodes = tdNode.getChildren().extractAllNodesThatMatch(a);

							log.debug("=====================a=======================\r\n");
							for (int n = 0; n < aNodes.size(); n++) {
								LinkTag aTag = (LinkTag) aNodes.elementAt(n);
								log.debug(aTag.getLinkText() + "，网址："
										+ aTag.getLink() + "\r\n");
								parts.put(aTag.getLinkText().replace("第", "")
										.replace("节", ""), aTag.getLink());
							}
							log.debug("=====================a=======================\r\n");
						}
					}
					log.debug("=====================td=======================\r\n");
				}
				log.debug("=====================tr=======================\r\n");
			}
		} catch (ParserException e1) {
			e1.printStackTrace();
		}
		
		return parts;
	}
	
	/**
	 * 
	 * 方法概述：获取域名
	 * 描述：获取域名
	 * @param url
	 * @return
	 * 返回类型：String
	 * 修改人：梁铭显 
	 * 修改时间：2013-7-25
	 */
	public String getHost(String url){
		String domain = "";
		try {
			URI uri = new URI(url);
			domain = uri.getHost();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return domain;
	}
	
	/**
	 * 
	 * 方法概述：获取正文
	 * 描述：获取正文
	 * @param html
	 * @param charSet
	 * @return
	 * 返回类型：String
	 * 修改人：梁铭显 
	 * 修改时间：2013-7-25
	 */
	public String getContent(String html,String charSet){
		String content = "";
		
		// 获取下文
		Parser parser = Parser.createParser(html, charSet);//用源码和页面的字符编码初始化一个Parser处理器
		
		NodeFilter td = new TagNameFilter("TD");
		NodeFilter style = new HasAttributeFilter("CLASS", "ART");
		NodeFilter contentFilter = new AndFilter(td, style);

		try {
			NodeList nodes = parser.extractAllNodesThatMatch(contentFilter);
			
			for(int i = 0; i < nodes.size(); i++){
				content = nodes.elementAt(i).getChildren().toHtml();
			}
		} catch (ParserException e) {
			e.printStackTrace();
		}
		
		content = content.replace("<br>", "\r\n");
		
		log.debug(content);
		
		return content;
	}
	
	/**
	 * 
	 * 方法概述：导出文本文件
	 * 描述：导出文本文件
	 * @param title
	 * @param content
	 * 返回类型：void
	 * 修改人：梁铭显 
	 * 修改时间：2013-7-25
	 */
	public void toTxt(String title,String content){
		File file = new File(title + ".txt");
		
		try {
			BufferedWriter output = new BufferedWriter(new FileWriter(file));
			output.write(content);
			output.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
